package com.bangmai.util;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.SocketException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.commons.net.ftp.FTP;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPFile;
import org.apache.commons.net.ftp.FTPReply;
import org.apache.log4j.Logger;

import com.bangmai.exception.ServiceException;

/**
 * FTP服务器操作文�?
 */
public class FTPClientUtil {
	Logger logger = Logger.getLogger(FTPClientUtil.class);

	public static final Log log = LogFactory.getLog(FTPClientUtil.class);

	// FTP server configuration--IP key,value is type of String
	public static final String p = "121.33.205.117";

	// FTP server configuration--Port key,value is type of Integer
	public static final String SERVER_PORT = "2221";

	// FTP server configuration--ANONYMOUS Log in key, value is type of Boolean
	public static final String IS_ANONYMOUS = "false";

	// user name of anonymous log in
	public static final String ANONYMOUS_USER_NAME = "anonymous";

	// password of anonymous log in
	public static final String ANONYMOUS_PASSWORD = "";

	// FTP server configuration--log in user name, value is type of String
	public static final String USER_NAME = "gzogydzsw";

	// FTP server configuration--log in password, value is type of String
	public static final String PASSWORD = "gzodzytg5tsdf";

	// FTP server configuration--PASV key, value is type of Boolean
	public static final String IS_PASV = "true";

	// FTP server configuration--working directory key, value is type of String
	// While logging in, the current directory is the user's home directory,
	// the workingDirectory must be set based on it.
	// Besides, the workingDirectory must exist, it can not be created
	// automatically.
	// If not exist, file will be uploaded in the user's home directory.
	// If not assigned, "/" is used.
	public static final String WORKING_DIRECTORY = File.separator + "TEST" + File.separator + "test05" + File.separator;

	/**
	 * 上传和下载文�?
	 * 
	 * @param ip
	 * @param port_
	 * @param userName
	 * @param userpassword
	 * @param remoteFilePath
	 * @param isUpload
	 * @param fileToUpload
	 * @param fileNameToDownload
	 * @param localFileStoredPath
	 * @throws SocketException
	 * @throws IOException
	 */
	public static final boolean transferFile(String ip, String port_, String userName, String userpassword,
			String remoteFilePath, boolean isUpload, String fileToUpload, String fileNameToDownload,
			String localFileStoredPath) throws SocketException, IOException {
		String host = ip;
		Integer port = Integer.parseInt(port_);
		Boolean isAnonymous = Boolean.parseBoolean(IS_ANONYMOUS);
		String username = userName;
		String password = userpassword;
		Boolean isPASV = Boolean.parseBoolean(IS_PASV);
		boolean isSuccess = false;
		// String workingDirectory = (String) serverCfg.get(WORKING_DIRECTORY);
		FTPClient ftpClient = new FTPClient();
		InputStream fileIn = null;
		OutputStream fileOut = null;
		try {

			log.debug("Connect to FTP server on " + host + ":" + port);
			ftpClient.connect(host, port);

			int reply = ftpClient.getReplyCode();
			if (!FTPReply.isPositiveCompletion(reply)) {
				log.error("FTP server refuses connection");
				System.out.println("FTP server refuses connection");

			}

			if (isAnonymous != null && isAnonymous) {
				username = ANONYMOUS_USER_NAME;
				password = ANONYMOUS_PASSWORD;
			}
			log.debug("Log in FTP server with username = " + username + ", password = " + password);
			if (!ftpClient.login(username, password)) {
				log.error("Fail to log in FTP server with username = " + username + ", password = " + password);
				System.out
						.println("Fail to log in FTP server with username = " + username + ", password = " + password);
				ftpClient.logout();

			}

			// Here we will use the BINARY mode as the transfer file type,
			// ASCII mode is not supportted.
			log.debug("Set type of the file, which is to upload, to BINARY.");
			ftpClient.setFileType(FTP.BINARY_FILE_TYPE);

			if (isPASV != null && isPASV) {
				log.debug("Use the PASV mode to transfer file.");
				ftpClient.enterLocalPassiveMode();
			} else {
				log.debug("Use the ACTIVE mode to transfer file.");
				ftpClient.enterLocalActiveMode();
			}

			// if (StringUtils.isBlank(remoteFilePath)) {
			// workingDirectory = "/";
			// }
			log.debug("Change current working directory to " + remoteFilePath);
			System.out.println("Change current working directory to " + remoteFilePath);
			ftpClient.changeWorkingDirectory(remoteFilePath);

			if (isUpload) { // upload

				File file = new File(fileToUpload);
				fileIn = new FileInputStream(file);
				log.debug("Upload file : " + file.getAbsolutePath() + " to FTP server with name : " + file.getName());
				if (!ftpClient.storeFile(file.getName(), fileIn)) {// 上传文件操作
					log.error("Fail to upload file, " + ftpClient.getReplyString());

					System.out.println("Fail to upload file, " + ftpClient.getReplyString());

				} else {
					log.debug("Success to upload file.");

					System.out.println("Success to upload file.");

					isSuccess = true;

				}

				// File file_ = new File(pathToUpload);
				// File[] tempList = file.listFiles();
				// for (File file2 : tempList) {
				// fileIn = new FileInputStream(file2);
				// log.debug("Upload file : " + file2.getAbsolutePath()
				// + " to FTP server with name : " + file2.getName());
				// if (!ftpClient.storeFile(file2.getName(), fileIn)) {
				// log.error("Fail to upload file, "
				// + ftpClient.getReplyString());
				//
				// System.out.println("Fail to upload file, "
				// + ftpClient.getReplyString());
				//
				// } else {
				// log.debug("Success to upload file.");
				//
				// System.out.println("Success to upload file.");
				//
				// }
				// }

				//
			} else { // download
				// make sure the file directory exists
				if (!fileNameToDownload.equals("")) {
					File fileStored = new File(localFileStoredPath);

					if (!fileStored.getParentFile().exists()) {
						fileStored.getParentFile().mkdirs();
					}
					fileOut = new FileOutputStream(fileStored);

					log.debug("Download file : " + fileNameToDownload + " from FTP server to local : "
							+ localFileStoredPath);

					System.out.println("Download file : " + fileNameToDownload + " from FTP server to local : "
							+ localFileStoredPath);

					if (!ftpClient.retrieveFile(fileNameToDownload, fileOut)) {
						log.error("Fail to download file, " + ftpClient.getReplyString());

					} else {
						log.debug("Success to download file.");
						isSuccess = true;

					}

				} else {

					FTPFile[] fs = ftpClient.listFiles();
					if (fs.length > 0) {
						for (FTPFile ff : fs) {

							// 6.写操作，将其写入到本地文件中
							File localFile = new File(localFileStoredPath + File.separator + ff.getName());
							System.out.print("从海关服务器加载的文件名�?:" + ff.getName());
							OutputStream is = new FileOutputStream(localFile);
							System.out.println("Download file : " + localFile.getName() + " from FTP server to local : "
									+ localFile.getPath());
							ftpClient.retrieveFile(ff.getName(), is);
							is.close();
							ftpClient.deleteFile(remoteFilePath + File.separator + ff.getName());
							System.out.println("delete file : " + remoteFilePath + File.separator + ff.getName());

						}
					} else {
						System.out.println("dir is empty");

					}

				}

			}

			ftpClient.noop();

			ftpClient.logout();

		} finally {
			if (ftpClient.isConnected()) {
				try {
					ftpClient.disconnect();
				} catch (IOException f) {
				}
			}
			if (fileIn != null) {
				try {
					fileIn.close();
				} catch (IOException e) {
				}
			}
			if (fileOut != null) {
				try {
					fileOut.close();
				} catch (IOException e) {
				}
			}
		}
		return isSuccess;
	}

	/**
	 * FTP连接
	 * 
	 * @param url
	 *            连接的地�?
	 * @param port
	 *            连接的端�?
	 * @param userName
	 *            登录到服务器的账�?
	 * @param userPassword
	 *            登录到服务器的密�?
	 * @return
	 */
	public static FTPClient getIntance(String url, int port, String userName, String userPassword) {
		FTPClient client = new FTPClient();
		try {
			client.connect(url, port);
			client.login(userName, userPassword);
		} catch (SocketException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		return client;
	}

	/**
	 * �?出FTP服务�?
	 * 
	 * @param client
	 */

	public static void close(FTPClient client) {
		try {
			if (!client.logout()) {
				client.logout();
			}
			if (client.isConnected()) {
				client.disconnect();
			}
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}

	/**
	 * FTP协议上传文件
	 */
	public static boolean uploadFile(String url, String port, String username, String password, String remotepath,
			String filename, InputStream input) {
		boolean success = false;
		FTPClient ftp = new FTPClient();
		try {
			int reply;
			ftp.connect(url, Integer.valueOf(port));// 连接FTP服务�?
			// 如果采用默认端口，可以使用ftp.connect(url)的方式直接连接FTP服务�?
			ftp.login(username, password);// 登录
			reply = ftp.getReplyCode();
			if (!FTPReply.isPositiveCompletion(reply)) {
				ftp.disconnect();
				return success;
			}
			ftp.changeWorkingDirectory(remotepath);
			ftp.storeFile(filename, input);
			input.close();
			ftp.logout();
			success = true;
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			if (ftp.isConnected()) {
				try {
					ftp.disconnect();
				} catch (IOException ioe) {
				}
			}
		}

		return success;
	}

	/**
	 * FTP协议下载文件
	 */
	public static boolean downFile(String url, int port, String username, String password, String remotePath,
			String fileName, String localPath) {
		boolean success = false;
		FTPClient ftp = new FTPClient();
		try {
			int reply;
			ftp.connect(url, port);
			// 如果采用默认端口，可以使用ftp.connect(url)的方式直接连接FTP服务�?
			ftp.login(username, password);// 登录
			reply = ftp.getReplyCode();
			if (!FTPReply.isPositiveCompletion(reply)) {
				ftp.disconnect();
				return success;
			}
			ftp.changeWorkingDirectory(remotePath);// 转移到FTP服务器目�?
			FTPFile[] fs = ftp.listFiles();
			for (FTPFile ff : fs) {
				if (ff.getName().equals(fileName)) {
					File localFile = new File(localPath + File.separator + ff.getName());

					OutputStream is = new FileOutputStream(localFile);
					if (ftp.retrieveFile(ff.getName(), is)) {
						System.out.println("文件下载完成");

					}
					is.close();
				}
			}

			ftp.logout();
			success = true;
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			if (ftp.isConnected()) {
				try {
					ftp.disconnect();
				} catch (IOException ioe) {
				}
			}
		}
		return success;
	}

	/**
	 * 获取远程FTP目录下的文件
	 */
	public static List<String> ftpDownFiles(String ip, String port, String userName, String userPassword,
			String ftpfilepath, String localpath, int type) throws Exception {
		List<String> xmList = new ArrayList<>();
		FTPClient ftpClient = null;
		FileInputStream fileInputStream;
		FileOutputStream fileOutputStream;
		ftpClient = new FTPClient();
		ftpClient.setConnectTimeout(5 * 1000);
		ftpClient.setDataTimeout(5 * 1000);
		ftpClient.connect(ip, Integer.valueOf(port));
		ftpClient.login(userName, userPassword);

		// �?测是否连接成�?
		ftpClient.enterLocalPassiveMode();
		int reply = ftpClient.getReplyCode();
		// 看返回的值是不是230，如果是，表示登陆成�?
		if (!FTPReply.isPositiveCompletion(reply)) {
			// 返回的code>=200&&code<300return
			ftpClient.disconnect();
			// 关闭FTP连接
		}
		ftpClient.setControlEncoding("UTF-8");
		// 设置字符编码
		ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);
		// 设置文件传输格式
		ftpClient.enterLocalPassiveMode();
		// System.out.println(ftpfilepath);
		ftpClient.changeWorkingDirectory(ftpfilepath);
		FTPFile[] fs = ftpClient.listFiles(ftpfilepath);
		// 得到当前ftp目录下的文件列表
		ByteArrayOutputStream baos = null;
		InputStream inputStream = null;
		BufferedInputStream bis = null;
		int i = 0;
		if (fs == null || fs.length == 0) {
			throw new ServiceException("远程目录没有文件");
		}
		// if (fs.length > 0) {
		try {
			for (FTPFile ff : fs) {
				if (ff.getName().equals(".") || ff.getName().equals("..")) {

				} else {
					i++;
					baos = new ByteArrayOutputStream();

					// new String(ff.getName().getBytes("GBK"), "ISO-8859-1")
					inputStream = ftpClient.retrieveFileStream(ff.getName());
					bis = new BufferedInputStream(inputStream);
					byte[] bufferByte = new byte[256];
					int l;
					while ((l = bis.read(bufferByte)) != -1) {
						baos.write(bufferByte, 0, l);
						baos.flush();
					}
					String xml = baos.toString("utf-8");
					ftpClient.getReply();
					// 1表示海关 海关回执需要解密操作
					if (type == 1) {
						xml = AESMessageSigner.decrypt(xml);
					} 
					xmList.add(xml);
					baos.close();
					bis.close();
					inputStream.close();
					
				}
			}
		} catch (Exception e) {
		}
		finally {

			try {
				ftpClient.logout();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			try {
				ftpClient.disconnect();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}

		return xmList;

	}

	/**
	 * 批量下载文件
	 */
	public static List<String> downloadFile(String url, int port, String username, String password, String remotePath,
			String localPath) throws Exception {
		boolean success = false;
		List<String> xmList = new ArrayList<>();
		FTPClient ftp = new FTPClient();
		ftp.setConnectTimeout(5 * 1000);
		ftp.setDataTimeout(5 * 1000);

		int reply;
		System.out.println("开始连接FTP服务器。。。");
		ftp.connect(url, port);
		ftp.login(username, password);// 登录
		//
		// ftp.enterLocalPassiveMode();
		// ftp.setFileType(FTP.BINARY_FILE_TYPE);
		// ftp.enterRemotePassiveMode();
		ftp.changeWorkingDirectory(remotePath);// 转移到FTP服务器目�?
		FTPFile[] fs = ftp.listFiles();
		ByteArrayOutputStream baos = null;
		InputStream inputStream = null;
		BufferedInputStream bis = null;
		int index = 0;
		if (ftp.isConnected()) {
			for (int i = 0; i < fs.length; i++) {
				File localFile = new File(localPath + File.separator + fs[i].getName());
				// if (!localFile.exists()) {
				// localFile.createNewFile();
				// OutputStream is = new FileOutputStream(localFile);
				System.out.println(localFile.getName());

				ftp.setFileType(FTP.BINARY_FILE_TYPE);

				baos = new ByteArrayOutputStream();
				inputStream = ftp.retrieveFileStream(new String(fs[i].getName().getBytes("GBK"), "ISO-8859-1"));
				bis = new BufferedInputStream(inputStream);
				byte[] bufferByte = new byte[256];
				int l;
				while ((l = bis.read(bufferByte)) != -1) {
					baos.write(bufferByte, 0, l);
					baos.flush();
				}

				ftp.getReply();
				System.out.println("第" + i + "个文件下载完成!!!");
				System.out.println(baos.toString("utf-8"));
				String xml = baos.toString("utf-8");
				xmList.add(xml);
				inputStream.close();
				// ftp.completePendingCommand();

				// ftp.retrieveFile(new String(fs[i].getName().getBytes("GBK"),
				// "ISO-8859-1"), is);
				// is.close();
				// inputStream.close();
				// bis.close();
				// baos.close();
				// is=null;
				// }
			}

		}
		success = true;
		// if (!ftp.completePendingCommand()) {
		// ftp.logout();
		// ftp.disconnect();
		// }
		//
		return xmList;
	}

	/**
	 * 单个文件删除远程FTP目录下的文件
	 */
	public static void deleteFTPDirs(String ip, int port, String userName, String userPassword, String remoteFile,String ftpfilename) {
		FTPClient client = new FTPClient();
		try {
			client.connect(ip, port);
			client.login(userName, userPassword);
			client.changeWorkingDirectory(remoteFile);
			client.deleteFile(ftpfilename);
		} catch (SocketException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} finally {
			try {
				client.logout();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			try {
				client.disconnect();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}

		}

	}

	/**
	 * 批量删除远程FTP服务器上�?个目录下的文�?
	 */
	public static void deleteFiles(String ip, int port, String userName, String userPassword, String remoteFile) throws Exception {
		FTPClient client = new FTPClient();
		try {
			client.connect(ip, port);
			client.login(userName, userPassword);
			client.changeWorkingDirectory(remoteFile);
			client.enterLocalPassiveMode();
			FTPFile[] files = client.listFiles();
			if (files.length > 0) {
				for (int i = 0; i < files.length; i++) {
					if (files[i].isFile()) {
						client.deleteFile(files[i].getName());
					}
				}
			}
		} catch (SocketException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} finally {
			try {
				client.logout();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			try {
				client.disconnect();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}

	}

}
